﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPOI.SS.Formula.Functions;
using ST.Buz.Base.Buz_ViewModel;
using ST.Buz.Base.Entity;
using ST.Buz.Base.Enums;
using ST.Buz.Base.ViewModel;
using ST.Buz.Service;
using ST.Common.Util;
using ST.Common.Util.Model;
using ST.Common.Util.Mvc;
using ST.Common.Util.Security;
using ST.Common.Util.Text;
using ST.WX.Common;
using ST.WX.MP.Model;
using ST.WX.XCX;
using ST.WX.XCX.Model;
using ST.WX.XCX.QRCode;
using ST.WX.XCX.QRCode.Model;
using ST.WX.XCX.SubscribeMsg;
using System;
using System.Net;
using System.Text;

namespace ST.Buz.Api.Controllers
{
	/// <summary>
	/// 微信小程序相关功能
	/// </summary>
	[AllowAnonymous]
	[Route("wx/xcx")]
	public class WX_XCXController : BaseController
	{
		private readonly WXXCXBaseApi xcxBaseApi;
		private readonly IServiceSysOrganization serviceSysOrganization;
		private readonly IServiceSysUser userServ;
		private readonly IServicePartner partnerServ;
		//private readonly ISessionService sessionServ;
		private readonly IServiceSysOAuth oauthServ;
		private readonly IServiceSysUserOAuth oauthUserServ;
		private readonly IServiceWXSession wxSessionServ;
		private readonly IServiceWXAppConfig wxAppConfigServ;
		private readonly WXSubscribeMsgApi wxSubscribeMsgApi;
		private readonly WXQRCodeApi wxQRCodeApi;

		public WX_XCXController(ILogger<WX_XCXController> _logger
			, WXXCXBaseApi _xcxBaseApi
			, IServiceSysOrganization _serviceSysOrganization
			, IServiceSysUser _userServ
			, IServicePartner _partnerServ
			, IServiceSysOAuth _oauthServ
			, IServiceSysUserOAuth _oauthUserServ
			, IServiceWXSession _wxSessionServ
			, IServiceWXAppConfig _wxAppConfigServ
			, WXSubscribeMsgApi _wxSubscribeMsgApi
			, WXQRCodeApi _wxQRCodeApi
			) : base(_logger)
		{
			xcxBaseApi = _xcxBaseApi;
			serviceSysOrganization = _serviceSysOrganization;
			userServ = _userServ;
			partnerServ = _partnerServ;
			//sessionServ = _sessionServ;
			oauthServ = _oauthServ;
			oauthUserServ = _oauthUserServ;
			wxSessionServ = _wxSessionServ;
			wxAppConfigServ = _wxAppConfigServ;

			wxSubscribeMsgApi = _wxSubscribeMsgApi;
			wxQRCodeApi = _wxQRCodeApi;
		}

		//[Route("notify")]
		//[HttpGet]
		//public ActionResult WXNotify(string appid, string signature, string timestamp, string nonce, string echostr)
		//{
		//	try
		//	{
		//		if (logger.IsEnabled(LogLevel.Debug))
		//		{
		//			logger.LogDebug("微信推送参数->appid:{0},signature:{1},timestamp:{2},nonce:{3},echostr:{4}",
		//				appid, signature, timestamp, nonce, echostr);
		//		}
		//		if (string.IsNullOrWhiteSpace(appid))
		//		{
		//			appid = GetRequestAppID();
		//		}
		//		if (!xcxBaseApi.CheckSignature(appid, signature, timestamp, nonce))
		//		{
		//			throw new Exception("微信签名校验失败");
		//		}

		//		return Content(echostr);
		//	}
		//	catch (Exception ex)
		//	{
		//		logger.LogError(ex, "处理微信推送消息出错");
		//		return Content(ex.Message);
		//	}
		//}

		//[Route("notify")]
		//[HttpPost]
		//public ActionResult WXHandler(string appid, string signature, string timestamp, string nonce, string echostr)
		//{
		//	try
		//	{
		//		if (logger.IsEnabled(LogLevel.Debug))
		//		{
		//			logger.LogDebug("微信推送参数->appid:{0},signature:{1},timestamp:{2},nonce:{3},echostr:{4}",
		//				appid, signature, timestamp, nonce, echostr);
		//		}

		//		//if (!CheckSignature(Request))
		//		//{
		//		//	throw new Exception("校验微信签名失败");
		//		//}

		//		#region 接收从微信后台POST过来的数据并解析
		//		string resultXml = string.Empty;
		//		StringBuilder buf = new StringBuilder();
		//		using (System.IO.Stream s = Request.Body)
		//		{
		//			int count = 0;
		//			byte[] buffer = new byte[1024];
		//			while ((count = s.Read(buffer, 0, buffer.Length)) > 0)
		//			{
		//				buf.Append(Encoding.UTF8.GetString(buffer, 0, count));
		//			}
		//		}
		//		resultXml = buf.ToString();
		//		if (logger.IsEnabled(LogLevel.Debug))
		//		{
		//			logger.LogDebug("微信推送内容->" + resultXml);
		//		}
		//		if (string.IsNullOrEmpty(resultXml))
		//		{
		//			throw new BuzException("微信推送内容为空");
		//		}
		//		//Dictionary<string, string> dicContent = new Dictionary<string, string>();
		//		//XmlDocument xmlDoc = new XmlDocument();
		//		//xmlDoc.LoadXml(resultXml);
		//		//XmlNode nodeRoot = xmlDoc.DocumentElement;
		//		//XmlNodeList nodes = nodeRoot.ChildNodes;
		//		//foreach (XmlNode xn in nodes)
		//		//{
		//		//	if (xn.NodeType == XmlNodeType.Element)
		//		//	{
		//		//		XmlElement xe = (XmlElement)xn;
		//		//		dicContent.Add(xe.Name, xe.InnerText);
		//		//	}
		//		//}
		//		//if (dicContent.ContainsKey("Event"))
		//		//{
		//		//	switch (dicContent["Event"])
		//		//	{
		//		//		case "subscribe"://关注事件
		//		//			DoSubscribe(dicContent);
		//		//			break;
		//		//		case "SCAN":
		//		//			DoScan(dicContent);//已关注之后，EventKey直接为场景值
		//		//			break;
		//		//	}
		//		//}
		//		#endregion
		//		return new EmptyResult();
		//	}
		//	catch (Exception ex)
		//	{
		//		logger.LogError(ex, "处理微信推送消息出错");
		//		return new EmptyResult();
		//	}
		//}

		/// <summary>
		/// 微信端登录（包括首次注册和登录）
		/// </summary>
		/// <param name="paras"></param>
		/// <returns></returns>
		[HttpPost("login")]
		public IActionResult Login([FromBody] JObject paras)
		{
			try
			{
				//CheckParams();

				UserSession userSession = null;

				string requestAppID = GetRequestAppID();
				string requestMPAppID = GetRequestMPAppID();
#if DEBUG
				if (logger.IsEnabled(LogLevel.Debug))
				{
					logger.LogDebug("请求参数->{0}", paras);

					if (Request.Headers != null)
					{
						StringBuilder buf = new StringBuilder();
						foreach (var hdr in Request.Headers)
						{
							buf.AppendFormat("{0}->{1}", hdr.Key, hdr.Value);
							buf.AppendLine();
						}
						logger.LogDebug("请求头部：{0}", buf);
					}
				}
#endif
				if (paras == null)//不传参数的时候，直接根据请求头部的认证信息刷新会话
				{
					userSession = RefreshSession(requestAppID, requestMPAppID);
				}
				else
				{
					string code = paras.Value<string>("code");
					if (string.IsNullOrEmpty(code))
					{
						var sessionCurrent = GetRawSessionFromRequest();
						//解密消息
						string rawData = paras.Value<string>("rawData");
						string encryptedData = paras.Value<string>("encryptedData");
						string iv = paras.Value<string>("iv");
						string signature = paras.Value<string>("signature");
						userSession = SyncWXInfo(sessionCurrent, rawData, encryptedData, iv, signature, requestAppID, requestMPAppID);
					}
					else
					{
						userSession = Login(requestAppID, code, requestMPAppID);
					}
				}
				var sessionNew = OnLoginCompleted(userSession, requestAppID, requestMPAppID);
				return GenSessionResult(sessionNew);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, "登录失败，" + ex.Message, (int)HttpStatusCode.InternalServerError);
			}
		}

		/// <summary>
		/// 使用用户名、密码验证登录并与当前微信绑定
		/// </summary>
		/// <param name="paras"></param>
		/// <returns></returns>
		[HttpPost("bind")]
		public IActionResult Bind([FromBody] JObject paras)
		{
			try
			{
				CheckParams();
				if (paras == null)
				{
					throw new ArgumentException("请求参数不能为空");
				}
				UserSession sessionCurrent = GetRawSessionFromRequest(false);
				string requestAppID = GetRequestAppID();
				//string originalAppID = GetOriginalAppID();

				if (logger.IsEnabled(LogLevel.Debug))
				{
					logger.LogDebug("请求参数->{0}", paras);
				}
				string type = paras.Value<string>("type");
				string userCode = paras.Value<string>("ucode");
				string userPasswd = paras.Value<string>("upasswd");
				if (string.IsNullOrEmpty(userCode) || string.IsNullOrEmpty(userPasswd))
				{
					throw new ArgumentException("请求参数不能为空");
				}
				var info = paras["info"];
				WXUserInfo userInfo = null;
				if (info != null)
				{
					userInfo = info.ToObject<WXUserInfo>();
				}
				SysOAuthDetail oauthDetail = null;
				if (userInfo != null)
				{
					oauthDetail = new SysOAuthDetail()
					{
						AvatarUrl = userInfo.avatarUrl,
						City = userInfo.city,
						Country = userInfo.country,
						NickName = userInfo.nickName,
						Province = userInfo.province
					};
					#region 处理性别
					switch (userInfo.gender)
					{
						case "1":
							oauthDetail.Gender = (int)Gender.男;
							break;
						case "2":
							oauthDetail.Gender = (int)Gender.女;
							break;
						default:
							oauthDetail.Gender = (int)Gender.未知;
							break;
					}
					#endregion
				}
				UserSession userSession = oauthServ.Bind(sessionCurrent, SessionType.微信, requestAppID, userCode, userPasswd, oauthDetail);

				return GenSessionResult(userSession);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, "用户登录绑定失败");
			}
		}

		/// <summary>
		/// 将小程序账户与公众号账户绑定
		/// </summary>
		/// <param name="paras"></param>
		/// <returns></returns>
		[HttpPost("mpbind")]
		public IActionResult MPBind([FromBody] JObject paras)
		{
			try
			{
				CheckParams();
				if (paras == null)
				{
					throw new ArgumentException("请求参数不能为空");
				}
				UserSession sessionCurrent = GetRawSessionFromRequest(false);
				string requestAppID = GetRequestAppID();
				//string originalAppID = GetOriginalAppID();

				if (logger.IsEnabled(LogLevel.Debug))
				{
					logger.LogDebug("请求参数->{0}", paras);
				}
				//string type = paras.Value<string>("type");//oauth类型
				var info = paras["info"];
				WXOAuthUserInfo userInfo = null;
				if (info != null)
				{
					userInfo = info.ToObject<WXOAuthUserInfo>();
				}
				SysOAuthDetail oauthDetail = null;
				if (userInfo != null)
				{
					oauthDetail = new SysOAuthDetail()
					{
						Type = SessionType.微信,
						AppID = userInfo.appid,
						OpenID = userInfo.openid,
						Subscribe = userInfo.subscribe == 1,
						NickName = userInfo.nickname,
						AvatarUrl = userInfo.headimgurl,
						Country = userInfo.country,
						Province = userInfo.province,
						City = userInfo.city
					};
					#region 处理性别
					switch (userInfo.sex)
					{
						case "1":
							oauthDetail.Gender = (int)Gender.男;
							break;
						case "2":
							oauthDetail.Gender = (int)Gender.女;
							break;
						default:
							oauthDetail.Gender = (int)Gender.未知;
							break;
					}
					#endregion
				}
				UserSession userSession = oauthServ.MPBind(sessionCurrent, requestAppID, oauthDetail);

				return GenSessionResult(userSession);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, "绑定公众号账户失败");
			}
		}

		/// <summary>
		/// 同步微信小程序用户信息，用户已经登录
		/// </summary>
		[HttpPost("syncinfo")]
		public IActionResult SyncWXInfo([FromBody] WXUserInfo rawData)
		{
			UserSession userSession = null;
			try
			{
				//CheckParams();

				userSession = GetRawSessionFromRequest();

				var requestAppID = GetRequestAppID();
				var mpAppID = GetRequestMPAppID();

				SysOAuthDetail oauth = new SysOAuthDetail()
				{
					NickName = rawData.nickName,
					Country = rawData.country,
					Province = rawData.province,
					City = rawData.city,
					AvatarUrl = rawData.avatarUrl,
				};
				#region 处理性别
				switch (rawData.gender)
				{
					case "1":
						oauth.Gender = (int)Gender.男;
						break;
					case "2":
						oauth.Gender = (int)Gender.女;
						break;
					default:
						oauth.Gender = (int)Gender.未知;
						break;
				}
				#endregion

				oauthServ.Update(userSession, SessionType.微信, requestAppID, oauth, mpAppID);

				return GenSessionResult(userSession);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (WXException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex, "同步微信信息出错");
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex, "同步微信信息出错");
				return new JsonResultBase(false, "同步微信信息失败", (int)HttpStatusCode.InternalServerError);
			}
		}

		/// <summary>
		/// 同步微信小程序用户信息，用户不一定已经登录，但必须调用过wx.login有了SessionKey
		/// </summary>
		/// <param name="userInfo"></param>
		/// <returns></returns>
		[HttpPost("sync")]
		public IActionResult SyncWXInfo([FromBody] WXGetUserInfoData userInfo)
		{
			UserSession sessionCurrent = null;
			try
			{
				//CheckParams();
				sessionCurrent = GetRawSessionFromRequest();

				var requestAppID = GetRequestAppID();
				var requestMPAppID = GetRequestMPAppID();

				sessionCurrent = SyncWXInfo(sessionCurrent, userInfo.rawData, userInfo.encryptedData, userInfo.iv, userInfo.signature, requestAppID, requestMPAppID);

				return GenSessionResult(sessionCurrent);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (WXException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex, "同步微信信息出错");
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex, "同步微信信息出错");
				return new JsonResultBase(false, "同步微信信息失败", (int)HttpStatusCode.InternalServerError);
			}
		}

		/// <summary>
		/// 用户注册
		/// </summary>
		/// <param name="userInfo"></param>
		/// <returns></returns>
		[HttpPost("register")]
		public IActionResult Register([FromBody] VM_Sys_UserRegister<WXUserInfo> vm)
		{
			try
			{
				CheckParams();
				if (vm == null)
				{
					throw new ArgumentException("请求参数不能为空");
				}
				if (string.IsNullOrEmpty(vm.user.Name))
				{
					throw new ArgumentException("姓名不能为空");
				}
				if (string.IsNullOrEmpty(vm.user.Mobile))
				{
					throw new ArgumentException("手机号不能为空");
				}
				//vm.user.DeptID;
				//vm.user.OrgID;
				var sessionCurrent = GetRawSessionFromRequest();
				SysOAuthDetail oauth = new SysOAuthDetail()
				{
					NickName = vm.info.nickName,
					Country = vm.info.country,
					Province = vm.info.province,
					City = vm.info.city,
					AvatarUrl = vm.info.avatarUrl,
				};
				#region 处理性别
				switch (vm.info.gender)
				{
					case "0":
						oauth.Gender = (int)Gender.未知;
						break;
					case "1":
						oauth.Gender = (int)Gender.男;
						break;
					case "2":
						oauth.Gender = (int)Gender.女;
						break;
					default:
						oauth.Gender = (int)Gender.未知;
						break;
				}
				#endregion

				string requestAppID = GetRequestAppID();
				//string originalAppID = GetOriginalAppID();

				var sessionNew = userServ.Register(SessionType.微信, requestAppID, sessionCurrent, vm.user, oauth);

				return GenSessionResult(sessionNew);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (WXException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex, "同步微信信息出错");
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex, "同步微信信息出错");
				return new JsonResultBase(false, "同步微信信息失败", (int)HttpStatusCode.InternalServerError);
			}
		}

		/// <summary>
		/// 更新个人信息
		/// </summary>
		/// <param name="userInfo"></param>
		/// <returns></returns>
		[HttpPost("update")]
		public IActionResult Update([FromBody] Sys_User vm)
		{
			try
			{
				//CheckParams();
				if (vm == null)
				{
					throw new ArgumentException("请求参数不能为空");
				}
				if (string.IsNullOrEmpty(vm.Name))
				{
					throw new ArgumentException("姓名不能为空");
				}
				if (string.IsNullOrEmpty(vm.Mobile))
				{
					throw new ArgumentException("手机号不能为空");
				}
				var sessionCurrent = GetRawSessionFromRequest();
				string requestAppID = GetRequestAppID();
				//string originalAppID = GetOriginalAppID();

				var sessionNew = userServ.Update(SessionType.微信, requestAppID, sessionCurrent, vm, null);

				return GenSessionResult(sessionNew);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (WXException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex, "更新个人信息出错");
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex, "更新个人信息出错");
				return new JsonResultBase(false, "更新个人信息失败，" + ex.Message, (int)HttpStatusCode.InternalServerError);
			}
		}

		/// <summary>
		/// 根据本地缓存的认证信息登录并返回刷新后的
		/// </summary>
		/// <param name="appID"></param>
		/// <returns></returns>
		private UserSession RefreshSession(string appID, string mpAppID)
		{
			try
			{
				UserSession sessionCurrent = GetRawSessionFromRequest();
				return oauthServ.Refresh(sessionCurrent, SessionType.微信, appID);
			}
			catch (AuthException ex)
			{
				throw new BuzException(ex.Message);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw new BuzException(ex.Message);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw new BuzException("刷新认证信息失败");
			}
		}

		/// <summary>
		/// 使用code登录
		/// </summary>
		/// <param name="appID"></param>
		/// <param name="code"></param>
		/// <returns></returns>
		private UserSession Login(string appID, string code, string mpAppID)
		{
			try
			{
				var appConfig = wxAppConfigServ.LoadOrGet(appID);
				var ret = xcxBaseApi.Login(appConfig.AppID, appConfig.AppSecret, code);
				var userSession = oauthServ.RegisterOrLogin(SessionType.微信, appConfig.AppID, ret.openid, ret.unionid, ret.session_key, null);
				return userSession;
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (WXException ex)
			{
				throw new BuzException(ex.Message);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw ex;
			}
		}

		/// <summary>
		/// 注销登录
		/// </summary>
		/// <param name="userID"></param>
		/// <returns></returns>
		[HttpPost("logout")]
		public IActionResult Logout()
		{
			try
			{
				UserSession sessionCurrent = GetRawSessionFromRequest(false);
				if (null == sessionCurrent || sessionCurrent.UserID <= 0)
				{
					throw new ArgumentException("未登录用户");
				}

				oauthUserServ.DeleteByUserID(sessionCurrent.UserID);
				return new JsonResultBase(true);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, "用户登录绑定失败");
			}
		}

		[HttpPost("home")]
		public IActionResult Home()
		{
			try
			{
				var vm = new VM_Home();
				vm.banners.Add(new VM_Banner
				{
					cover = "http://zhangji.sqcdrj.com/upload/chenyuxiaoguan.png"
				});
				return new JsonResultBase(vm);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message, ex.StatusCode);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, "用户登录绑定失败");
			}
		}

		/// <summary>
		/// 使用已有的sessionkey解密用户信息，并返回更新后的session
		/// </summary>
		/// <param name="rawData"></param>
		/// <param name="encryptedData"></param>
		/// <param name="iv"></param>
		/// <param name="signature"></param>
		/// <returns></returns>
		private UserSession SyncWXInfo(UserSession sessionCurrent, string rawData, string encryptedData, string iv, string signature, string appID, string mpAppID)
		{
			try
			{
				if (logger.IsEnabled(LogLevel.Debug))
				{
					logger.LogDebug("微信登录参数->rawData：{0},encryptedData：{1},iv：{2},signature：{3},mpappid:{4}", rawData, encryptedData, iv, signature, mpAppID);
				}
				if (string.IsNullOrEmpty(rawData) || string.IsNullOrEmpty(encryptedData) || string.IsNullOrEmpty(iv) || string.IsNullOrEmpty(signature))
				{
					throw new ArgumentException("微信登录关键信息不能为空");
				}
				if (EncryptHelper.SHA1Hash(rawData + sessionCurrent.Sessionkey) != signature)
				{
					throw new AuthException("校验微信用户信息的签名不一致，登录可能已过期");
				}
				string decryptedDataStr = EncryptHelper.WXAESDecrypt(encryptedData, iv, sessionCurrent.Sessionkey);
				if (string.IsNullOrEmpty(decryptedDataStr))
				{
					throw new AuthException("解密微信用户信息为空，登录可能已过期");
				}
				WXDecryptedData decryptedData = JsonConvert.DeserializeObject<WXDecryptedData>(decryptedDataStr);
				if (string.Compare(decryptedData.watermark.appid, appID) != 0)
				{
					throw new AuthException("解密后的AppID与来源AppID不一致");
				}
				SysOAuthDetail oauth = new SysOAuthDetail()
				{
					NickName = decryptedData.nickName,
					Country = decryptedData.country,
					Province = decryptedData.province,
					City = decryptedData.city,
					AvatarUrl = decryptedData.avatarUrl,
				};
				#region 处理性别
				switch (decryptedData.gender)
				{
					case "0":
						oauth.Gender = (int)Gender.未知;
						break;
					case "1":
						oauth.Gender = (int)Gender.男;
						break;
					case "2":
						oauth.Gender = (int)Gender.女;
						break;
					default:
						oauth.Gender = (int)Gender.未知;
						break;
				}
				#endregion
				sessionCurrent.OpenID = decryptedData.openId;
				sessionCurrent.UnionID = decryptedData.unionId;
				
				return oauthServ.Update(sessionCurrent, SessionType.微信, appID, oauth, mpAppID);
			}
			//catch (JsonReaderException ex)
			//{
			//	throw new AuthException("解析失败");
			//}
			catch (AuthException ex)
			{
				throw new BuzException(ex.Message);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw new BuzException(ex.Message);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw new BuzException("解密、解析用户信息失败");
			}
		}

		[HttpGet("info")]
		public IActionResult ShowInfo(string appid, string nonce)
		{
			try
			{
				if (string.IsNullOrWhiteSpace(appid))
				{
					appid = GetRequestAppID();
				}
				if (string.Compare(EncryptHelper.SHA1Hash(appid + DateTime.Now.ToString("yyyyMMdd")), nonce) != 0)
				{
					throw new WXException("访问非法");
				}
				var appConfig = wxAppConfigServ.LoadOrGet(appid);
				string accessToken = xcxBaseApi.BaseApi.GetAccessToken(appConfig.AppID, appConfig.AppSecret);
				return new JsonResultBase(accessToken);
			}
			catch (WXException ex)
			{
				logger.LogError(ex, "获取App信息出错");
				return new JsonResultBase(false, "获取App信息出错，" + ex.Message, (int)HttpStatusCode.InternalServerError);
			}
			catch (Exception ex)
			{
				logger.LogError(ex, "获取App信息出错");
				return new JsonResultBase(false, "获取App信息出错，" + ex.Message, (int)HttpStatusCode.InternalServerError);
			}
		}

		/// <summary>
		/// 解密微信相关信息
		/// </summary>
		/// <param name="paras"></param>
		/// <returns></returns>
		[HttpPost("decrypt")]
		public IActionResult Decrypt([FromBody] JObject paras)
		{
			try
			{
				//CheckParams();
				if (paras == null)
				{
					throw new BuzException("参数不能为空");
				}
				string requestAppID = GetRequestAppID();

				var sessionCurrent = GetRawSessionFromRequest();
				//解密消息
				string encryptedData = paras.Value<string>("encryptedData");
				string iv = paras.Value<string>("iv");
				var result = xcxBaseApi.Decrypt(encryptedData, iv, sessionCurrent.Sessionkey);
				return new JsonResultBase(result);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, "解密微信相关信息失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 发送订阅消息
		/// </summary>
		/// <returns></returns>
		[HttpPost("sendsubscribe")]
		public IActionResult SendSubscribeMsg([FromBody] VM_WX_XCXSubscribeMsg vm)
		{
			try
			{
				var sessionCurrent = GetRawSessionFromRequest();
				var appID = GetRequestAppID();
				var appConfig = wxAppConfigServ.LoadOrGet(appID);
				wxSubscribeMsgApi.Send(appConfig.AppID, appConfig.AppSecret, sessionCurrent.OpenID, vm.tplid, vm.page, vm.data);
				return new JsonResultBase(true);
			}
			catch (BuzException ex)
			{
				throw ex;
			}
			catch (WXException ex)
			{
				throw new BuzException(ex.Message);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				throw ex;
			}
		}

		/// <summary>
		/// 微信支付结果通知
		/// </summary>
		[HttpPost("notify")]
		public IActionResult Notify()
		{
			try
			{
				//NotifyBase nofity = new NotifyBase(this.Request, this.Response);
				//WxPayData notifyData = null;
				//try
				//{
				//	notifyData = nofity.GetNotifyData();
				//}
				//catch (WXPayException ex)
				//{
				//	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[" + ex.Message + "]]></return_msg></xml>");
				//}
				//catch (Exception ex)
				//{
				//	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[" + ex.Message + "]]></return_msg></xml>");
				//}

				////检查支付结果中transaction_id是否存在
				////string wxOrderNo = Convert.ToString(notifyData.GetValue("transaction_id"));
				//string orderNo = Convert.ToString(notifyData.GetValue("out_trade_no"));
				//if (string.IsNullOrEmpty(orderNo))
				//{
				//	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付结果中订单号不存在]]></return_msg></xml>");
				//}
				////string cash_fee = Convert.ToString(notifyData.GetValue("cash_fee"));
				////if (string.IsNullOrEmpty(cash_fee))
				////{
				////	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付结果中现金支付金额不存在]]></return_msg></xml>");
				////}
				////int cashPay;
				////if (!int.TryParse(cash_fee, out cashPay))
				////{
				////	log.Error("微信通知返回的订单号（" + orderNo + "）的支付金额为" + cash_fee + "不正确");
				////	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付结果中现金支付金额不正确]]></return_msg></xml>");
				////}

				//string total_fee = Convert.ToString(notifyData.GetValue("total_fee"));
				//if (string.IsNullOrEmpty(total_fee))
				//{
				//	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付结果中总金额不存在]]></return_msg></xml>");
				//}
				//int totalPay;
				//if (!int.TryParse(total_fee, out totalPay))
				//{
				//	log.Error("微信通知返回的订单号（" + orderNo + "）的支付金额为" + totalPay + "不正确");
				//	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付结果中总金额不正确]]></return_msg></xml>");
				//}

				//string time_end = Convert.ToString(notifyData.GetValue("time_end"));
				//if (string.IsNullOrEmpty(time_end))
				//{
				//	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[支付结果中支付时间不存在]]></return_msg></xml>");
				//}
				//string attach = Convert.ToString(notifyData.GetValue("attach"));
				//using (EMISEntities dbCtx = new EMISEntities())
				//{
				//	EMIS_Order order = null;
				//	if (!string.IsNullOrEmpty(attach))
				//	{
				//		order = dbCtx.EMIS_Order.SingleOrDefault(m => m.OrderNo == attach);//使用原订单号

				//		if (order == null)
				//		{
				//			log.Error("系统本地未找到微信通知返回的追加订单号（" + orderNo + "），原订单号（" + attach + "）");
				//			return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[系统本地未找到微信通知返回的订单号" + orderNo + "]]></return_msg></xml>");
				//		}
				//		//order.ZJJE = cashPay;
				//		order.ZJJE = totalPay;
				//		order.ZJOrderState = (int)ZJStateEnum.已追加;
				//		DateTime dt;
				//		if (DateTime.TryParseExact(time_end, "yyyyMMddHHmmss", null, System.Globalization.DateTimeStyles.None, out dt))
				//		{
				//			order.ZJDate = dt;
				//		}
				//		dbCtx.SaveChanges();
				//	}
				//	else
				//	{
				//		order = dbCtx.EMIS_Order.SingleOrDefault(m => m.OrderNo == orderNo);
				//		if (order == null)
				//		{
				//			log.Error("系统本地未找到微信通知返回订单号（" + orderNo + "）");
				//			return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[系统本地未找到微信通知返回的订单号" + orderNo + "]]></return_msg></xml>");
				//		}
				//		//order.ZFJE = cashPay;
				//		order.ZFJE = totalPay;
				//		DateTime dt;
				//		if (DateTime.TryParseExact(time_end, "yyyyMMddHHmmss", null, System.Globalization.DateTimeStyles.None, out dt))
				//		{
				//			order.ZFDate = dt;
				//		}
				//		order.OrderState = (int)OrderStateEnum.已支付;
				//		dbCtx.SaveChanges();
				//	}
				//}
				//查询订单，判断订单真实性
				//if (!QueryOrder(transaction_id))
				//{
				//	return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[订单查询失败]]></return_msg></xml>");
				//}
				//查询订单成功
				return Content("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[ok]]></return_msg></xml>");
			}
			catch (Exception ex)
			{
				logger.LogError(ex, ex.InnerException != null ? ex.InnerException.Message : ex.Message);
				return Content("<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[" + ex.Message + "]]></return_msg></xml>");
			}
		}

		/// <summary>
		/// 生成小程序码/小程序二维码
		/// </summary>
		[HttpGet("qr")]
		public IActionResult QRCode()
		{
			try
			{
				//CheckParams();
				//var sessionCurrent = GetRawSessionFromRequest();
				string appID = TextHelper.GetString(Request.Query["appid"]);
				string path = TextHelper.GetString(Request.Query["path"]);
				int width = TextHelper.GetInt(Request.Query["width"]);
				string type = TextHelper.GetString(Request.Query["type"]);
				var appConfig = wxAppConfigServ.LoadOrGet(appID);
				WXQRCodeResult result = null;
				switch (type)
				{
					case "qr"://小程序二维码
						result = wxQRCodeApi.CreateQRCode(appConfig.AppID, appConfig.AppSecret, path, width);
						break;
					case "wxa"://小程序码
						result = wxQRCodeApi.GetWXACode(appConfig.AppID, appConfig.AppSecret, path, width);
						break;
					default:
						result = wxQRCodeApi.GetWXACode(appConfig.AppID, appConfig.AppSecret, path, width);
						break;
				}
				return File(result.buffer, result.contentType);
			}
			catch (AuthException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (BuzException ex)
			{
				return new JsonResultBase(false, ex.Message);
			}
			catch (ArgumentException ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, ex.Message, (int)HttpStatusCode.BadRequest);
			}
			catch (Exception ex)
			{
				logger.LogError(ex.InnerException ?? ex, ex.Message);
				return new JsonResultBase(false, "生成小程序码/小程序二维码失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
			}
		}

		/// <summary>
		/// 微信小程序登录完成后的业务自定义操作
		/// </summary>
		/// <param name="sessionCurrent"></param>
		/// <returns></returns>
		public UserSession OnLoginCompleted(UserSession sessionCurrent, string requestAppID, string requestMPAppID)
		{
			sessionCurrent.PartnerID = partnerServ.GetDefaultPartnerID(requestAppID, sessionCurrent);
			//获取单位绑定的PartnerID
			if (sessionCurrent.OrgID > 0 && sessionCurrent.OrgPartnerID == 0)
			{
				var org = serviceSysOrganization.Get(sessionCurrent.OrgID);
				if (org != null)
				{
					sessionCurrent.OrgType = org.Type;
					sessionCurrent.OrgPartnerID = org.PartnerID;
				}
			}
			return sessionCurrent;
		}

		#region 辅助方法
		/// <summary>
		/// 当前请求的小程序AppID
		/// </summary>
		protected virtual string RequestAppID
		{
			get { return GetRequestAppID(); }
		}
		#endregion
	}
}